/*
 * Copyright © OpenAtom Foundation.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package io.iec.edp.caf.databaseobject.generate;

import io.iec.edp.caf.databaseobject.DataTypeConverter;
import io.iec.edp.caf.databaseobject.DatabaseFuncConverter;
import io.iec.edp.caf.databaseobject.api.entity.DataType;
import io.iec.edp.caf.generator.baseInfo.AnnotationInfo;
import io.iec.edp.caf.generator.baseInfo.AnnotationType;
import io.iec.edp.caf.generator.baseInfo.TypeInfo;
import io.iec.edp.caf.generator.field.FieldGenerator;
import io.iec.edp.caf.databaseobject.DataTypeUtil;
import io.iec.edp.caf.databaseobject.api.entity.DbType;
import io.iec.edp.caf.databaseobject.api.entity.DatabaseObjectColumn;
import io.iec.edp.caf.databaseobject.api.entity.DatabaseObjectTable;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.StringLiteral;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * @author liu_wei
 */
public class PrimaryKeyFieldGenerator extends FieldGenerator {
    DatabaseObjectColumn column;
    DatabaseObjectTable table;
    private DbType dbType;

    public DbType getDbType() {
        return dbType;
    }

    public void setDbType(DbType dbType) {
        this.dbType = dbType;
    }

    public PrimaryKeyFieldGenerator() {

    }

    public PrimaryKeyFieldGenerator(DatabaseObjectColumn column, DatabaseObjectTable table) {
        this.column = column;
        this.table = table;
    }

    @Override
    protected TypeInfo getFieldType() {
        DataTypeUtil util = new DataTypeUtil();
        return util.getTypeInfoByDataType(column.getDataType());
    }

    @Override
    protected String getFieldName() {
        return this.column.getCode();
    }

    @Override
    protected ArrayList<Modifier.ModifierKeyword> getAccessModifier() {
        ArrayList<Modifier.ModifierKeyword> arrayList = new ArrayList<>();
        arrayList.add(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
        return arrayList;
    }

    @Override
    public ArrayList<AnnotationInfo> getAttributeList() {
        ArrayList<AnnotationInfo> result = new ArrayList<AnnotationInfo>();
        AnnotationInfo annotationInfo = new AnnotationInfo();
        annotationInfo.setAnnotationType(AnnotationType.Normal);
        annotationInfo.setTypeInfo(new TypeInfo("Column"));
        HashMap map = new HashMap();

        String columnDefination = getColumnDefinition();
        StringLiteral defination = ast.newStringLiteral();
        defination.setLiteralValue(columnDefination);
        map.put("columnDefinition", defination);

        StringLiteral nameStringLiteral = ast.newStringLiteral();
        nameStringLiteral.setLiteralValue(column.getCode());
        map.put("name", nameStringLiteral);

        map.put("nullable", ast.newBooleanLiteral(column.isNullable()));
        map.put("unique", ast.newBooleanLiteral(column.isUnique()));
        annotationInfo.setParams(map);

        result.add(annotationInfo);
        return result;
    }

    public String getColumnDefinition() {
        //根据数据库类型拼出字段类型
        String columnDefination = getDataTypeStr();
        if (column.getDefaultValue() != null && column.getDefaultValue().length() > 0) {
            columnDefination += getDefaultStr();
        }
        return columnDefination;
    }

    private String getDataTypeStr() {
        String type = "";

        if (dbType == DbType.Oracle && (column.getDataType() == DataType.Varchar || column.getDataType() == DataType.Char) && column.getLength() > 4000) {
            column.setDataType(DataType.Clob);
            column.setLength(0);
        }
        if (dbType == DbType.Oracle && (column.getDataType() == DataType.NVarchar || column.getDataType() == DataType.Char) && column.getLength() > 2000) {
            column.setDataType(DataType.NClob);
            column.setLength(0);
        }
        //DB2的Decimal长度只支持31
        if(dbType == DbType.DB2 && (column.getDataType() == DataType.Decimal) && (column.getPrecision() > 31))
        {
            column.setPrecision(31);
        }
        DataType dataType = column.getDataType();

        if (DataTypeConverter.getInstance().IsExistConverMapping(column.getDataTypeStr())) {
            type = DataTypeConverter.getInstance().GetDataType(column.getDataTypeStr(), dbType.toString());

        } else if (dataType == DataType.LongInt) {
            if (dbType == DbType.Oracle) {
                type = "number(20)";
            } else {
                type = "bigint";
            }


        } else if (dataType == DataType.SmallInt) {
            type = "smallint";
        } else {
            type = column.getDataTypeStr();
        }

        if (dataType == DataType.Varchar || dataType == DataType.Char || dataType == DataType.NChar || dataType == DataType.NVarchar) {
            type = type + "(" + column.getLength() + ")";
        }
        return type;
    }

    private String getDefaultStr() {
        String defaultStr = " default ";
        String defaultValue = column.getDefaultValue();
        if (defaultValue.contains("'")) {
            defaultValue = defaultValue.substring(defaultValue.indexOf("'") + 1, defaultValue.lastIndexOf("'") - 1);
        }
        if (DatabaseFuncConverter.getInstance().isExistConverMapping(defaultValue)) {
            defaultStr += DatabaseFuncConverter.getInstance().getFuncName(defaultValue, dbType.toString());
        } else if (column.getDataType() == DataType.Int || column.getDataType() == DataType.LongInt || column.getDataType() == DataType.SmallInt || column.getDataType() == DataType.Float) {
            defaultStr += defaultValue;
        } else if (column.getDataType() == DataType.Boolean) {
            if (defaultValue == "0" || defaultValue == "false" || defaultValue == "f") {
                if (dbType == DbType.PgSQL || dbType == DbType.Kingbase || dbType == DbType.HighGo || dbType == DbType.OpenGauss) {
                    defaultStr += "false";
                } else {
                    defaultStr += "0";
                }
            } else {
                if (dbType == DbType.PgSQL || dbType == DbType.Kingbase || dbType == DbType.HighGo || dbType == DbType.OpenGauss) {
                    defaultStr += "true";
                } else {
                    defaultStr += "1";
                }
            }
        } else if (column.getDataType() == DataType.TimeStamp && dbType == DbType.Oracle) {
            defaultStr += "TO_TIMESTAMP('" + defaultValue + "', 'YYYY-MM-DD HH24:MI:SS.FF')";
        } else if (column.getDataType() == DataType.DateTime && dbType == DbType.Oracle) {
            defaultStr += "TO_DATE('" + defaultValue + "', 'YYYY-MM-DD HH24:MI:SS')";
        } else {
            defaultStr += "'" + defaultValue + "'";
        }
        return defaultStr;
    }
}
